import numpy as np

class UAV:
    def __init__(self, grid_size,id,charging_stations,num_position_action,num_energy_action):
        #无人机基础信息
        self.id = id
        self.speed = 25
        
        #无人机能量信息
        self.energy = 100
        self.has_charge = False
        self.charging_stations = charging_stations
        self.num_energy_action = num_energy_action
        self.epsilon = 0.1
        
        #无人机的位置信息
        self.grid_size = grid_size
        self.position = (np.random.randint(grid_size), np.random.randint(grid_size))
        self.num_position_action = num_position_action
        
        # 无人机历史信息
        self.history_position = []
        self.history_length = 10
        

    def select_energy_action(self, action):
        return 1
    
    def select_cruise_action(self,action_values):
        # 从有效动作中选择最佳动作
        action = [0,1,2,3]
        if np.random.uniform(0, 1) < 0.1:
            return np.random.choice(action)  # 随机选择一个有效动作
        else:
            # 根据 action_values 选择最佳动作
            best_action = 0
            max_q_value = action_values[best_action]
            for i in action:
                if action_values[i] > max_q_value:
                    best_action = i
                    max_q_value = action_values[i]
        
        return best_action

    def reduce_energy(self, amount):
        # 扣除电量
        self.energy -= amount
        if self.energy < 0:
            self.energy = 0  # 确保电量不为负数
            
            
    def execute_cruise_action(self, action):
        """
        根据动作更新位置并消耗对应电量
        假设动作0-3分别表示上下左右移动，动作4表示原地停留
        """
        # 定义每个动作的电量消耗（例如，上下左右移动消耗5单位电量，停留消耗2单位电量）
        
        # 当前坐标
        x, y = self.position
        distance_per_time = self.speed
        reward1 = 0


        # 根据动作更新位置
        if action == 0 and y < self.grid_size - 1:  # 向上移动
            y += distance_per_time
        elif action == 1:  # 向下移动
            y -= distance_per_time
        elif action == 2:  # 向左移动
            x -= distance_per_time
        elif action == 3:  # 向右移动
            x += distance_per_time
        # 停留位置不变
        
        # 检查是否超出边界并限制
        if x < 0:
            x = 0  # 如果x小于0，设为最小值0
            reward1 -=10000
            print("hit the wall")
        elif x >= self.grid_size:
            x = self.grid_size - 1  # 如果x超出grid_size，设为最大值grid_size-1
            reward1 -=10000
            print("hit the wall")
        
        if y < 0:
            y = 0  # 如果y小于0，设为最小值0
            reward1 -= 10000
            print("hit the wall")
        elif y >= self.grid_size:
            y = self.grid_size - 1  # 如果y超出grid_size，设为最大值grid_size-1
            reward1 -=10000
            print("hit the wall")
        
        # 更新位置
        self.position = (x, y)
        
        # 更新历史路径
        self.history_position.append(self.position)
        if len(self.history_position) > self.history_length:
            self.history_position.pop(0)
        
        # 执行电量消耗
        self.reduce_energy(1)
        return reward1

    def serve_ground_user(self, ground_user_position,communacation_demand):
        """
        为地面用户提供服务，计算服务的电量消耗和奖励
        """
        distance = np.linalg.norm(np.array(self.position) - np.array(ground_user_position))
        
        # 假设服务电量消耗与距离成正比
        energy_cost = distance * communacation_demand /1000   # 每单位距离消耗2单位电量
        
        if self.energy >= energy_cost:
            # 可以为用户提供服务
            self.reduce_energy(energy_cost)
            return 1  # 服务成功，奖励1
        else:
            return -1  # 电量不足，不能提供服务


    def get_state(self):
        return np.array([self.position[0], self.position[1], self.energy])
